package services;

import dao.ProblemJpaController;
import dao.exceptions.NonexistentEntityException;
import entities.Contest;
import entities.Problem;
import exceptions.DatabaseException;
import exceptions.NonExistentObjectException;
import exceptions.PreexistingObjectException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import util.EnumSearchParameter;
import vo.VOProblem;

/**
 *
 * @author sbaldrich
 */
public class ProblemService {

    private static ProblemJpaController pc;

    public static ProblemJpaController getInstance() {
        if (pc == null) {
            pc = new ProblemJpaController();
        }
        return pc;
    }
    private static ContestService cs;

    public static ContestService getContestService() {
        if (cs == null) {
            cs = new ContestService();
        }
        return cs;
    }

    public void save(VOProblem vo) throws Exception {
        pc = getInstance();
        cs = getContestService();
        Problem p = findObject(vo.getProblemCode());
        if (p != null) {
            throw new PreexistingObjectException("Problem Code");
        }
        p = new Problem(vo);
        try {
            p.setContest(cs.findObject(vo.getContestCode()));
            pc.create(p);
        } catch (Exception e) {
            if (e instanceof NonExistentObjectException) {
                throw new NonExistentObjectException("Contest");
            }
            throw new DatabaseException("ProblemService.save");
        }
    }

    public VOProblem find(String problemCode) throws Exception {
        Problem p = findObject(problemCode);
        if (p == null) {
            return null;
        }
        return p.getVO();

    }

    public Problem findObject(String problemCode) throws Exception {
        pc = getInstance();
        try {
            return pc.findProblem(problemCode);
        } catch (Exception e) {
            return null;
        }
    }

    public void update(VOProblem vo) throws Exception {
        pc = getInstance();
        cs = getContestService();
        Problem p = pc.findProblem(vo.getIdProblem());
        p.setDescription(vo.getDescription());
        p.setDifficulty(vo.getDifficulty());
        p.setName(vo.getName());
        p.setProblemCode(vo.getProblemCode());
        p.setTime(vo.getTime());
        p.setContest(cs.findObject(vo.getContestCode()));
        updateObject(p);
    }

    public void updateObject(Problem p) throws Exception {
        pc = getInstance();
        try {
            pc.edit(p);
        } catch (Exception e) {
            if (e instanceof NonexistentEntityException) {
                throw new NonExistentObjectException();
            }
            throw new DatabaseException("ProblemService.update Operation");
        }
    }

    public void delete(VOProblem vo) throws Exception {
        pc = getInstance();
        try {
            pc.destroy(vo.getIdProblem());
        } catch (Exception e) {
            if (e instanceof NonexistentEntityException) {
                throw new NonExistentObjectException();
            }
            throw new DatabaseException("ProblemService.delete Operation");
        }
    }

    public ArrayList<VOProblem> findall() throws Exception {
        pc = getInstance();
        try {
            ArrayList<VOProblem> ret = new ArrayList<VOProblem>();
            Vector<Problem> l = (Vector<Problem>) pc.findProblemEntities();
            if (l == null || l.isEmpty()) {
                return null;
            }
            for (Problem u : l) {
                ret.add(u.getVO());
            }
            return ret;
        } catch (Exception e) {
            if (e instanceof NonexistentEntityException) {
                throw new NonExistentObjectException();
            }
            throw new DatabaseException();
        }
    }

    public ArrayList<VOProblem> findall(EnumSearchParameter parameter, String value) {
        if (!parameter.equals(EnumSearchParameter.CONTEST)) {
            return null;
        }
        cs = getContestService();
        Contest c = null;
        try {
            c = cs.findObject(value);
            if (c == null) {
                return null;
            }
            List<Problem> l = (List<Problem>) c.getProblemList();
            if (l == null || l.isEmpty()) {
                return null;
            }
            ArrayList<VOProblem> ret = new ArrayList<VOProblem>();
            for (Problem p : l) {
                ret.add(p.getVO());
            }
            return ret;
        } catch (Exception e) {
            
            return null;
        }

    }
}
